package com.sugon.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.consts.ErmsCodePrefix;
import com.sugon.dao.DevRepairRecordDao;
import com.sugon.entity.DevRepairRecordEntity;
import com.sugon.entity.DeviceInfoEntity;
import com.sugon.entity.SysUserEntity;
import com.sugon.entity.dto.DevRepairTicketExportParam;
import com.sugon.modules.device.consts.DeviceTicketSource;
import com.sugon.modules.device.consts.enums.DevRepairTicketStatusEnum;
import com.sugon.service.DevRepairRecordService;
import com.sugon.service.DeviceInfoService;
import com.sugon.service.SparePartConsumRecordService;
import com.sugon.service.SysUserService;
import com.sugon.utils.Constant;
import com.sugon.utils.ShiroUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 维修记录记录Service实现类
 *
 * @author YuXD
 * @date 2023-05-20
 */
@Service("deviceRepairRecordService")
public class DevRepairRecordServiceImpl implements DevRepairRecordService {

    @Resource
    private DevRepairRecordDao devRepairRecordDao;
    @Resource
    private SparePartConsumRecordService sparePartConsumRecordService;
    @Resource
    private DeviceInfoService deviceInfoService;
    @Resource
    private SysUserService userService;

    @Override
    public int queryTotal(Map<String, Object> map) {
        return devRepairRecordDao.queryTotal(map);
    }

    @Override
    public List<DevRepairRecordEntity> queryList(Map<String, Object> map) {
        return devRepairRecordDao.queryList(map);
    }

    @Override
    public DevRepairRecordEntity queryObject(String id) {
        return devRepairRecordDao.queryObject(id);
    }

    @Override
    public List<DevRepairRecordEntity> queryListByDevId(String devId) {
        DevRepairRecordEntity queryParam = new DevRepairRecordEntity();
        queryParam.setDevId(devId);
        return queryList(BeanUtil.beanToMap(queryParam));
    }

    @Override
    public DevRepairRecordEntity queryObjectByRepairCode(String repairCode) {
        Map<String, Object> param = MapUtil.newHashMap();
        param.put("repairCode", repairCode);
        List<DevRepairRecordEntity> repairRecordList = queryList(param);
        return CollectionUtil.isNotEmpty(repairRecordList) ? repairRecordList.get(0) : null;
    }

    @Override
    public boolean save(DevRepairRecordEntity repairRecord) {
        repairRecord.setId(RandomUtil.randomString(32));
        // 新增时将原维修记录ID与主键设置为一样
        repairRecord.setOriginRepairRecordId(repairRecord.getId());
        if (StrUtil.isEmpty(repairRecord.getRepairCode())) {
            repairRecord.setRepairCode(generateUniqueCode(repairRecord));
        }
        // 设置默认故障时长
        if (repairRecord.getFaultDuration() == null) {
            repairRecord.setFaultDuration(0L);
        }
        // 默认设置为为制定预防措施
        if (repairRecord.getIsPrevented() == null) {
            repairRecord.setIsPrevented(0);
        }
        repairRecord.setCreateBy(ShiroUtils.getUserId());
        repairRecord.setCreateTime(DateUtil.date());
        repairRecord.setUpdateBy(repairRecord.getCreateBy());
        repairRecord.setUpdateTime(repairRecord.getCreateTime());
        repairRecord.setDelFlag(Constant.IS_NOT_DEL_INT);
        return devRepairRecordDao.save(repairRecord) > 0;
    }

    @Override
    public String generateUniqueCode(Object object) {
        // 工单编号的日期部分：优先根据开始维修的那一天，如果没有则默认为当前
        Date startRepairTime = null;
        if (object != null) {
            DevRepairRecordEntity repairTicket = (DevRepairRecordEntity) object;
            startRepairTime = repairTicket.getRepairStartDate();
        }
        if (startRepairTime == null) {
            startRepairTime = cn.hutool.core.date.DateUtil.date();
        }
        String dateStr = cn.hutool.core.date.DateUtil.format(startRepairTime, DatePattern.PURE_DATE_PATTERN);
        String repairTicketCodePrefix = ErmsCodePrefix.MAINTENANCE_TICKET_CODE_PREFIX + dateStr + "-";
        String lastestRepairTicketCode = devRepairRecordDao.getLastestRepairTicketCode(repairTicketCodePrefix);
        if (StrUtil.isEmpty(lastestRepairTicketCode)) {
            return repairTicketCodePrefix + "0001";
        } else {
            return com.sugon.modules.utils.StrUtil.increase(lastestRepairTicketCode, repairTicketCodePrefix, 4, 1);
        }
    }

    @Override
    public boolean update(DevRepairRecordEntity repairRecord) {
        repairRecord.setUpdateTime(DateUtil.date());
        return devRepairRecordDao.update(repairRecord) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteBatch(String[] ids) {
        int rows = 0;
        for (String id : ids) {
            // 删除备件耗用记录
            sparePartConsumRecordService.delete("REPAIR", id);
            // 删除维修记录
            rows += devRepairRecordDao.delete(id);
        }
        return rows;
    }

    @Override
    public List<DevRepairTicketExportParam> prepareExportData(Map<String, Object> params) {
        List<DevRepairTicketExportParam> exportDataList = devRepairRecordDao.prepareExportData(params);
        return Optional.ofNullable(exportDataList).orElse(CollectionUtil.newArrayList());
    }

    /**
     * @param excelInputStream excel输入流
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int importExcelFromStream(InputStream excelInputStream) throws Exception {
        ImportParams importParams = new ImportParams();
        importParams.setHeadRows(1);

        // 从上传文件中读取叉车台账列表
        List<DevRepairRecordEntity> repairRecordList = ExcelImportUtil.importExcel(excelInputStream, DevRepairRecordEntity.class, importParams);
        if (CollectionUtil.isEmpty(repairRecordList)) {
            return 0;
        }
        int importRows = 0;
        // 设备匹配MAP
        Map<String, DeviceInfoEntity> devMap = MapUtil.newHashMap();
        // ERMS用户匹配MAP
        Map<String, String> userMap = MapUtil.newHashMap();
        // 工单状态枚举
        Map<String, Integer> devStatusMap = DevRepairTicketStatusEnum.getDescMap();
        // 工单来源键值对
        Map<String, String> sourseMap = DeviceTicketSource.getSourseMap();

        List<String> unExistedList = CollectionUtil.newArrayList();

        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreProperties("source", "devStatus");
        for (DevRepairRecordEntity param : repairRecordList) {
            // 尝试获取设备信息
            String devCode = param.getDevCode();
            if (StrUtil.isEmpty(devCode)) {
                continue;
            }
            // 设置设备ID
            DeviceInfoEntity device = devMap.get(devCode);
            if (device == null) {
                device = deviceInfoService.getInfoByDevCode(devCode);
                if (device == null) {
                    unExistedList.add(devCode);
                    continue;
                }
                devMap.put(devCode, device);
                param.setDevId(device.getId());
                param.setWorkshopId(StrUtil.sub(device.getDeptCode(), 0, 4));
            } else {
                param.setDevId(device.getId());
                param.setWorkshopId(StrUtil.sub(device.getDeptCode(), 0, 4));
            }
            /*
             来源逻辑：只要有报修人，那就是系统报修，其余则为一键报修
             */
            // 设置设备状态
            String source = sourseMap.get(param.getSource());
            if (StrUtil.isNotEmpty(source)) {
                param.setSource(source);
            } else {
                if (StrUtil.isNotEmpty(param.getUploadName())) {
                    param.setSource(DeviceTicketSource.SYSTEM.name());
                    String ermsUserId = userMap.get(param.getUploadName());
                    if (StrUtil.isNotEmpty(ermsUserId)) {
                        param.setUploadId(ermsUserId);
                    } else {
                        SysUserEntity ermsUser = userService.queryByNickname(param.getUploadName());
                        if (ermsUser != null) {
                            param.setUploadId(ermsUser.getUserId());
                            userMap.put(param.getUploadName(), ermsUser.getUserId());
                        }
                    }
                } else {
                    param.setSource(DeviceTicketSource.HMI.name());
                }
            }

            // 设置报修人
            if (StrUtil.isNotEmpty(param.getRepairUsername())) {
                String ermsUserId = userMap.get(param.getRepairUsername());
                if (StrUtil.isNotEmpty(ermsUserId)) {
                    param.setRepairUser(ermsUserId);
                } else {
                    SysUserEntity ermsUser = userService.queryByNickname(param.getRepairUsername());
                    if (ermsUser != null) {
                        param.setRepairUser(ermsUser.getUserId());
                        userMap.put(param.getRepairUsername(), ermsUser.getUserId());
                    }
                }
            }

            // 设置设备状态
            Integer devStatus = devStatusMap.get(param.getDevStatusDesc());
            if (devStatus != null) {
                param.setDevStatus(devStatus);
            } else {
                param.setDevStatus(DevRepairTicketStatusEnum.END_REPAIR.getValue());
            }

            /*
                判断是否有维修单号：
                1、如果没有，则肯定新增
                2、如果有，则去系统中查询
                    如果存在，则更新
                    否则，则新增
             */
            String repairCode = param.getRepairCode();
            if (StrUtil.isNotEmpty(repairCode)) {
                DevRepairRecordEntity existedRepairRecord = queryObjectByRepairCode(repairCode);
                if (existedRepairRecord != null) {
                    BeanUtil.copyProperties(param, existedRepairRecord, copyOptions);
                    importRows += update(existedRepairRecord) ? 1 : 0;
                    continue;
                }
            }
            importRows += save(param) ? 1 : 0;
        }
        return importRows;
    }

}
